/*
 * This code is property of CoreObjects. Use, duplication and disclosure
 * in any form without permission of copyright holder is prohibited.
 *
 */
package com.nen.session;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.beanutils.BeanUtils;

/**
 * Checks for valid login. Extracts session and user information.
 * Adds new cookies to response - jsessionid cookie and useremail cookie
 *
 * @author amitm
 */
public class TempFilter implements Filter {

    private static String JSESSIONID_COOKIE_NAME = "_nenjsid";
    private static String USEREMAIL_COOKIE_NAME = "_nenue";
    private static String COOKIE_DOMAIN_NAME = ".nenonline.org";
    private static String ONCE_PER_REQUEST_ATTR_NAME = "_cookie_filter_applied_";

    public void init(FilterConfig fc) throws ServletException {
        System.out.println("Inside init");
        JSESSIONID_COOKIE_NAME = getParamValue(fc.getInitParameter("JSESSIONID_COOKIE_NAME"), JSESSIONID_COOKIE_NAME);
        USEREMAIL_COOKIE_NAME = getParamValue(fc.getInitParameter("USEREMAIL_COOKIE_NAME"), USEREMAIL_COOKIE_NAME);
        COOKIE_DOMAIN_NAME = getParamValue(fc.getInitParameter("COOKIE_DOMAIN_NAME"), COOKIE_DOMAIN_NAME);
    }

    public void doFilter(ServletRequest request,
            ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {
        System.out.println("Inside CookieFilter, url = "+((HttpServletRequest)request).getRequestURL()+", query="+((HttpServletRequest)request).getQueryString());
        System.out.println("redirectUrl="+((HttpServletRequest)request).getParameter("redirectURL"));
        System.out.println("method="+((HttpServletRequest)request).getParameter("method"));

        System.out.println("Response is committed? "+response.isCommitted());

        if(request.getAttribute(ONCE_PER_REQUEST_ATTR_NAME) == null) {
            request.setAttribute(ONCE_PER_REQUEST_ATTR_NAME, Boolean.TRUE);

            System.out.println("Applying CookieFilter once");

            HttpSession javaSession = ((HttpServletRequest) request).getSession(false);
            if (javaSession == null || javaSession.getAttribute("loginUserDetails") == null) {
                System.out.println("Login has not yet happened. Not setting subdomain cookie!");

                chain.doFilter(request, response);

                System.out.println("2 Post chain.doFilter");
                System.out.println("2 Response is committed? "+response.isCommitted());
                return;
            }
            System.out.println("Login has happened. Setting additional cookies");

            String javaSessionId = javaSession.getId();
            System.out.println("Java session id = " + javaSessionId);
            Cookie[] cookies = ((HttpServletRequest) request).getCookies();

            Cookie jsidCookie = new Cookie(JSESSIONID_COOKIE_NAME, javaSessionId);
            jsidCookie.setDomain(COOKIE_DOMAIN_NAME);
            jsidCookie.setPath("/");
            Cookie useremailCookie = new Cookie(USEREMAIL_COOKIE_NAME, getUserEmail(javaSession));
            useremailCookie.setDomain(COOKIE_DOMAIN_NAME);
            useremailCookie.setPath("/");

            setCookie(cookies, (HttpServletResponse) response, jsidCookie, true);
            setCookie(cookies, (HttpServletResponse) response, useremailCookie, true);

            chain.doFilter(request, response);

            System.out.println("3 Post chain.doFilter");
            System.out.println("3 Response is committed? "+response.isCommitted());
        }
        else {
            System.out.println("Skipping cookie filter as it is already applied on this request");
            chain.doFilter(request, response);
            System.out.println("4 Post chain.doFilter");
            System.out.println("4 Response is committed? "+response.isCommitted());
        }

        System.out.println("Exiting CookieFilter.doFilter");
    }

    private static boolean setCookie(Cookie[] cookies, HttpServletResponse response, Cookie newCookie, boolean checkExisting) {
        Cookie existingCookie = getCookieWithName(cookies, newCookie.getName());
        boolean newCookieAdded = false;
        if (checkExisting && existingCookie != null) {
            System.out.println("Cookie already exists! => " + getStringValue(existingCookie));
        } else {
            response.addCookie(newCookie);
            System.out.println(getStringValue(newCookie));
            newCookieAdded = true;
            System.out.println("New cookie added => " + getStringValue(newCookie));
        }

        return newCookieAdded;
    }

    private static String getUserEmail(HttpSession session) {
        Object loginUserDetails = session.getAttribute("loginUserDetails");
        String userEmail = "";
        try {
            userEmail = BeanUtils.getProperty(loginUserDetails, "userEmail");
        } catch (IllegalAccessException ex) {
            ex.printStackTrace();
        } catch (InvocationTargetException ex) {
            ex.printStackTrace();
        } catch (NoSuchMethodException ex) {
            ex.printStackTrace();
        }

        return userEmail;
    }

    private static String getStringValue(Cookie cookie) {
        return "Name=" + cookie.getName() + ",value=" + cookie.getValue() + ",domain=" + cookie.getDomain();
    }

    private static Cookie getCookieWithName(Cookie[] cookies, String name) {
        Cookie returnCookie = null;
        if (cookies != null) {
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                if (name.equals(cookie.getName())) {
                    returnCookie = cookie;
                }
            }
        }
        return returnCookie;
    }

    public void destroy() {
        System.out.println("Inside destroy");
    }

    private static String getParamValue(String paramValue, String defaultValue) {
        String returnValue = defaultValue;
        if (paramValue != null) {
            String temp = paramValue.trim();
            if (temp.length() > 0) {
                returnValue = temp;
            }
        }
        return returnValue;
    }
}
